package com.ruoyi.common.config;

import com.ruoyi.common.util.Threads;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author LiuXiaoYu
 * @date 2021/9/4- 18:50
 */
@Configuration
public class AsyncConfig {

    @Value("${spring.executor.task.corePoolSize}")
    private Integer corePoolSize;
    @Value("${spring.executor.task.maxPoolSize}")
    private Integer maxPoolSize;
    @Value("${spring.executor.task.queueCapacity}")
    private Integer queueCapacity;
    @Value("${spring.executor.task.threadNamePrefix}")
    private String threadNamePrefix;
    @Value("${spring.executor.task.shutdown}")
    private boolean shutdown;

    @Bean("asyncLog")
    public ThreadPoolTaskExecutor asyncLog(){
        ThreadPoolTaskExecutor threadPoolTaskExecutor=new ThreadPoolTaskExecutor();
        //核心线程数
        threadPoolTaskExecutor.setCorePoolSize(corePoolSize);
        //最大线程数
        threadPoolTaskExecutor.setMaxPoolSize(maxPoolSize);
        //队列容量
        threadPoolTaskExecutor.setQueueCapacity(queueCapacity);
        //线程名称前缀
        threadPoolTaskExecutor.setThreadNamePrefix(threadNamePrefix);
        // 拒绝策略 CALLER_RUNS：不在新线程中执行任务，而是有调用者所在的线程来执行
        //TODO 应该自定义策略 出现问题 通知开发者
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //设置所有任务执行完毕后关闭线程池
        threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(shutdown);
        threadPoolTaskExecutor.initialize();

        return threadPoolTaskExecutor;
    }

    /**
     * 执行周期性或定时任务
     */
    @Bean(name = "scheduledExecutorService")
    protected ScheduledExecutorService scheduledExecutorService()
    {
        return new ScheduledThreadPoolExecutor(corePoolSize,
                new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build())
        {
            @Override
            protected void afterExecute(Runnable r, Throwable t)
            {
                super.afterExecute(r, t);
                Threads.printException(r, t);
            }
        };
    }
}
